﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace gChartSharp
{
    /// <summary>
    /// The base class from which all Charts are derived
    /// </summary>
    public abstract class ChartBase
    {
        /// <summary>
        /// 
        /// </summary>
        protected const string APIURL = @"http://chart.apis.google.com/chart?";


        /// <summary>
        /// 
        /// </summary>
        public abstract ChartType ChartType { get; }
        

        /// <summary>
        /// 
        /// </summary>
        public SizeParam Size
        {
            get { return mSize ?? (mSize = new SizeParam()); }
            set { mSize = value; }
        }
        private SizeParam mSize;


        /// <summary>
        /// 
        /// </summary>
        public DataSeriesParam Data
        {
            get { return mData ?? (mData = new DataSeriesParam()); }
            set { mData = value; }
        }
        private DataSeriesParam mData;


        /// <summary>
        /// Default ctor
        /// </summary>
        protected ChartBase()
        { }


        /// <summary>
        /// The simplest chart constructor to initialize the minimum required
        /// properties to render all graphs.
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="dataSets"></param>
        /// <param name="encType"></param>
        public ChartBase(int width, int height, EncodingType encType, float[] dataSets)
        {
            Size = new SizeParam(width, height);
            Data = new DataSeriesParam() { Params = new List<float[]>() { dataSets } };
            Data.EncodingType = encType;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="dataSets"></param>
        public ChartBase(int width, int height, float[] dataSets)
            : this(width, height, EncodingType.Text, dataSets) { }


        /// <summary>
        /// Initializes a graph with no data sets
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="encType"></param>
        public ChartBase(int width, int height, EncodingType encType)
        {
            Size = new SizeParam(width, height);
            Data.EncodingType = encType;
        }


        /// <summary>
        /// Initializes a graph with no data sets
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public ChartBase(int width, int height) 
            : this(width, height, EncodingType.Text) { }


        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected virtual string RenderUrl()
        {
            StringBuilder sb = new StringBuilder();

            // Append base API URL
            sb.Append(String.Format("{0}cht={1}{2}{3}", APIURL, ChartType.GetDescriptionAttribute(), Size.Render(), Data.Render()));

            // Use reflection to get properties contained in the class.
            PropertyInfo[] properties = this.GetType().GetProperties();

            // Try to cast each of the properties to an IRenderable.  If successful, render param.
            foreach (PropertyInfo pi in properties)
            {
                IRenderable chartParam = pi.GetValue(this, null) as IRenderable;
                if (chartParam != null)
                    sb.Append(chartParam.Render());
            }

            return sb.ToString();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual string Render()
        {
            return RenderUrl();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual string RenderHtml()
        {
            return String.Format("<img src=\"{0}\" />", RenderUrl());
        }
    }
}
